package de.cbf.cam.dsa.model.entities.weapon;

import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToMany;

import de.cbf.cam.dsa.model.base.BaseWeapon;
import de.cbf.cam.dsa.model.entities.OneNPC;
import de.cbf.cam.dsa.model.entities.WeaponStyle;
import de.cbf.cam.dsa.model.entities.maneuvers.ManeuverDesc;
import de.cbf.cam.dsa.model.entities.weapon.valueModifier.WeaponValueModifier;

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class OneWeapon extends BaseWeapon {	
	
	/**
	 * @uml.property  name="valueModifiers"
	 * @uml.associationEnd  multiplicity="(0 -1)" elementType="de.cbf.cam.dsa.model.entities.weapon.valueModifier.WeaponValueModifier"
	 */
	protected List<WeaponValueModifier> valueModifiers = new ArrayList<WeaponValueModifier>();
	
	public static final String PROPERTYNAME ="OneWeapon";
	/**
	 * @uml.property  name="propertyChangeSupport"
	 */
	public PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
//========================
//		constructors
//========================
	
	public OneWeapon() {
		super();		
	}

//========================
//	   public methods
//========================

//========================
//    standard methods
//========================
	@Override
	public String toString() {			
		return name+"("+weaponType+")";
	}
//========================
// 	   private methods
//========================

//========================
// 	SHORT property access
//========================
	/**
	 * get all maneuvers that are possible with this weaponMain no matter what style/SF/etc.
	 * @return the possibleManeuvers
	 */
	public List<ManeuverDesc> getPossibleManeuversWithWeapon(){
		List<ManeuverDesc> maneuvers = new ArrayList<ManeuverDesc>();
		for(int i=0;i<styles.size();i++){
			WeaponStyle style = styles.get(i);
			for(int j = 0;j<style.getPossibleManeuvers().size();j++){
				if(!maneuvers.contains(style.getPossibleManeuvers().get(j))){
					maneuvers.add(style.getPossibleManeuvers().get(j));
				}
			}
		}
		return maneuvers;
	}
	
	
	public boolean addValueModifier(WeaponValueModifier weaponValueModifier) {
		boolean result = this.valueModifiers.add(weaponValueModifier);
		//modify weaponMain
		weaponValueModifier.modifyWeaponValue(this);
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"valueModifiers",null,valueModifiers);
		return result;		
	}
	public boolean removeValueModifier(WeaponValueModifier weaponValueModifier) {
		//get modifier to remove
		boolean contains = this.valueModifiers.remove(weaponValueModifier);
		if(contains){
			//only if element is there and so we really remove: unmodify weaponMain, property change
			weaponValueModifier.unModifyWeaponValue(this);
			propertyChangeSupport.firePropertyChange(PROPERTYNAME+"valueModifiers",null,valueModifiers);
		}				
		return contains;		
	}
	public void removeValueModifiersByType(int type) {
		//get modifier to remove
		for(int i =0;i<valueModifiers.size();i++){
			WeaponValueModifier modifier = valueModifiers.get(i);
			if(modifier.getType()==type){
				modifier.unModifyWeaponValue(this);
			}
		}			
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"valueModifiers",null,valueModifiers);				
	}
	
	@ManyToMany(cascade =CascadeType.ALL)	
	public List<WeaponValueModifier> getValueModifiers() {
		return valueModifiers;
	}
	public void setValueModifiers(List<WeaponValueModifier> modifiers) {
		this.valueModifiers = modifiers;
	}
	/**
	 * @param tpDiceNumber the tpDiceNumber to set
	 */
	public void setTpDiceNumber(int tpDiceNumber) {
		this.tpDiceNumber=tpDiceNumber;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"tpDiceNumber",null,tpDiceNumber);
	}

	/**
	 * @param tpDiceSides the tpDiceSides to set
	 */
	public void setTpDiceSides(int tpDiceSides) {
		this.tpDiceSides=tpDiceSides;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"tpDiceSides",null,tpDiceSides);
	}

	/**
	 * @param tpBonus the tpBonus to set
	 */
	public void setTpBonus(int tpBonus) {
		this.tpBonus= tpBonus;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"tpBonus",null,tpBonus);
	}

	/**
	 * choose best style for this character too
	 * @param character
	 * @return
	 */
	public abstract WeaponInUse useIt(OneNPC character,String styleTalentToUse);
	
//========================
//		listeners
//========================

}
